﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ILN.MVC.Datetimepicker
{
    using System.Linq.Expressions;
    using System.Web.Mvc;
    using Resource = ILN.MVC.Datetimepicker.App_LocalResources.DatetimepickerResource;

    public class DateTimePickerExtensionUtils
    {
        public static void AddValidationProperties<TModel, TValue>(HtmlHelper<TModel> self,
            Expression<Func<TModel, TValue>> expression, ModelMetadata metadata, TagBuilder tag)
        {
            var fieldName = ExpressionHelper.GetExpressionText(expression);
            var fullBindingName = self.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
            var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);

            var validationAttributes = self.GetUnobtrusiveValidationAttributes(fullBindingName, metadata);
            foreach (var key in validationAttributes.Keys)
            {
                if (!tag.Attributes.ContainsKey(key))
                    tag.Attributes.Add(key, validationAttributes[key].ToString());
            }
        }

        internal static TagBuilder BuildDivWrapper(string id)
        {
            TagBuilder e = new TagBuilder("div");
            e.Attributes.Add("class", "input-group date");
            e.Attributes.Add("id", id);
            e.Attributes.Add("data-iln-description", "div wrapper");
            return e;
        }
        public static TagBuilder BuildDataElement(ModelMetadata metadata, string divWrapperId, DatetimepickerOptions options)
        {
            return BuildDataElement(metadata.PropertyName, divWrapperId, ((DateTime?)metadata.Model), options);
        }

        public static TagBuilder BuildDataElement(string name, string divWrapperId, DateTime? value, DatetimepickerOptions options)
        {
            TagBuilder input = new TagBuilder("input");
            input.Attributes.Add("type", "hidden");
            input.Attributes.Add("class", "iln-datetimepicker");
            input.Attributes.Add("data-iln-maskforat", Resource.dataMaskForat);
            if (value != null && value.HasValue)
                input.Attributes.Add("data-value", value.Value.ToString());
            input.Attributes.Add("data-iln-propertyname", name);

            input.Attributes.Add("data-iln-wrapperid", divWrapperId);
            input.Attributes.Add("data-iln-description", "Data and information for the iln js creator");
            if (options != null)
                SetAttributesOptions(options, input);

            return input;
        }

        private static void SetAttributesOptions(DatetimepickerOptions options, TagBuilder input)
        {
            SetAttributeOptions(() => options.allowInputToggle, input, false);
            SetAttributeOptions(() => options.calendarWeeks, input, false);
            SetAttributeOptions(() => options.collapse, input, true);
            SetAttributeOptions(() => options.daysOfWeekDisabled, input, "[]");
            SetAttributeOptions(() => options.dayViewHeaderFormat, input, Resource.dayViewHeaderFormat);
            SetAttributeOptions(() => options.debug, input, false);
            //SetAttributeOptions(() => options.defaultDate, input, "false");
            SetAttributeOptions(() => options.disabledHours, input, "false");
            SetAttributeOptions(() => options.disabledTimeIntervals, input, "false");
            SetAttributeOptions(() => options.enabledDates, input, "false");
            SetAttributeOptions(() => options.enabledHours, input, "false");
            SetAttributeOptions(() => options.extraFormats, input, "false");
            SetAttributeOptions(() => options.focusOnShow, input, true);
            SetAttributeOptions(() => options.format, input, Resource.format);
            SetAttributeOptions(() => options.inline, input, false);
            SetAttributeOptions(() => options.icons, input, @"{
                        ""time"": ""glyphicon glyphicon-time"",
                        ""date"": ""glyphicon glyphicon-calendar"",
                        ""up"": ""glyphicon glyphicon-chevron-up"",
                        ""down"": ""glyphicon glyphicon-chevron-down"",
                        ""previous"": ""glyphicon glyphicon-chevron-left"",
                        ""next"": ""glyphicon glyphicon-chevron-right"",
                        ""today"": ""glyphicon glyphicon-screenshot"",
                        ""clear"": ""glyphicon glyphicon-trash"",
                        ""close"": ""glyphicon glyphicon-remove""}");
            SetAttributeOptions(() => options.keepInvalid, input, false);
            SetAttributeOptions(() => options.keepOpen, input, false);
            SetAttributeOptions(() => options.locale, input, "");
            SetAttributeOptions(() => options.maxDate, input, null);
            SetAttributeOptions(() => options.minDate, input, null);
            SetAttributeOptions(() => options.showClear, input, false);
            SetAttributeOptions(() => options.showClose, input, false);
            SetAttributeOptions(() => options.showTodayButton, input, false);
            SetAttributeOptions(() => options.sideBySide, input, false);
            SetAttributeOptions(() => options.stepping, input, 1);
            SetAttributeOptions(() => options.toolbarPlacement, input, ToolbarPlacementOption.DEFAULT);
            SetAttributeOptions(() => options.tooltips, input, $@"{{ ""tooltips"" : {{
                ""today"":""{Resource.today}"",
                ""clear"":""{Resource.clear}"",
                ""close"":""{Resource.close}"",
                ""selectMonth"":""{Resource.selectMonth}"",
                ""prevMonth"":""{Resource.prevMonth}"",
                ""nextMonth"":""{Resource.nextMonth}"",
                ""selectYear"":""{Resource.selectYear}"",
                ""prevYear"":""{Resource.prevYear}"",
                ""nextYear"":""{Resource.nextYear}"",
                ""selectDecade"":""{Resource.selectDecade}"",
                ""prevDecade"":""{Resource.prevDecade}"",
                ""nextDecade"":""{Resource.nextDecade}"",
                ""prevCentury"":""{Resource.prevCentury}"",
                ""nextCentury"":""{Resource.nextCentury}""
            }}}}");
            SetAttributeOptions(() => options.useCurrent, input, true);
            SetAttributeOptions(() => options.useStrict, input, false);
            SetAttributeOptions(() => options.viewDate, input, false);
            SetAttributeOptions(() => options.viewMode, input, ViewModeOptions.DAYS);
            SetAttributeOptions(() => options.widgetPositioning, input, @"{""horizontal"": ""auto"", ""vertical"": ""auto""}");
        }

        public static void SetAttributeOptions<T>(Expression<Func<T>> expression, TagBuilder tag, T defaultValue)
        {
            var member = (MemberExpression)expression.Body;
            string propertyName = member.Member.Name;
            T value = expression.Compile()();

            if (value == null)
                value = defaultValue;

            if (value != null && value.GetType() == typeof(bool))
                tag.Attributes.Add("data-" + propertyName, value.ToString().ToLower());
            else if(value != null)
                tag.Attributes.Add("data-" + propertyName, value.ToString());
        }
        internal static TagBuilder BuildMainInput(ModelMetadata metadata)
        {
            return BuildMainInput(metadata.PropertyName, ((DateTime?)metadata.Model));
        }

        internal static TagBuilder BuildMainInput(string name, DateTime? value)
        {

            TagBuilder input = new TagBuilder("input");
            input.Attributes.Add("type", "text");
            input.AddCssClass("form-control");
            input.Attributes.Add("data-val", "true");
            input.Attributes.Add("name", name);
            input.Attributes.Add("id", name);
            input.Attributes.Add("data-iln-description", "main input");
            if (value != null && value.HasValue)
            {
                input.Attributes.Add("value", value.Value.ToString());
            }

            return input;
        }

        internal static TagBuilder BuildSpanElement()
        {
            TagBuilder span1 = new TagBuilder("span");
            span1.Attributes.Add("class", "input-group-addon");
            span1.Attributes.Add("data-iln-description", "span1");

            TagBuilder span2 = new TagBuilder("span");
            span2.Attributes.Add("class", "glyphicon glyphicon-calendar");
            span2.Attributes.Add("data-iln-description", "span2");
            span1.InnerHtml = span2.ToString();
            return span1;
        }
    }
}